package com.zhenai.rocyuan.modules.threadupdown;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.SocketAddress;
import org.apache.log4j.Logger;

/**
 * 客户端与服务器共同使用的方法
 * 
 * @author hzgk
 * 
 */
public class BaseSocketTool {
	private static final Logger log = Logger.getLogger(BaseSocketTool.class);

	/**
	 * 读取文件
	 * 
	 * @param filePath
	 *            文件接收路径
	 * @param out
	 * @param in
	 * @param isBreakpointContinue
	 *            是否支持断点续传
	 * @return
	 */
	public boolean readFile(String filePath, ObjectOutputStream out, ObjectInputStream in, boolean isBreakpointContinue) {
		boolean flag = true;
		FileOutputStream fileOut = null;
		File saveFile = null;
		long len = 0;
		try {
			// 读 文件名 , 文件长度 , 写入 跳过长度

			BaseSocket.cc++;
			saveFile = new File(filePath, BaseSocket.cc + in.readUTF());
			if (!saveFile.getParentFile().exists()) {
				saveFile.getParentFile().mkdirs();
			}
			if (!saveFile.exists()) {
				saveFile.createNewFile();
			}
			len = in.readLong();

			// 断点续传的情况
			long skip = 0;
			if (isBreakpointContinue) {
				skip = saveFile.length();
			}
			out.writeLong(skip);
			out.flush();

			fileOut = new FileOutputStream(saveFile, skip > 0 ? true : false);

			log.debug("--begin to receive file[len:" + len + "]" + Thread.currentThread().getName());

			long needLong = len - skip;
			long nowLong = 0;

			byte[] buf = new byte[BaseSocket.BUFFER_SIZE];
			int i = 0;
			while (true) {
				i++;
				int read = 0;
				// int available = in.available();
				if (in != null) {
					read = in.read(buf);
				}
				if (i == 500) {
					i = 0;
					System.out.print(",");
				}
				// if (available == 6) {
				// log.error("^^^^^^^^" + read + "~~~~" + available);
				// byte[] copyOf = Arrays.copyOf(buf, 6);
				// String theEnd = new String(copyOf);
				// if (theEnd.equals(BaseSocket.TRANSMIT_END)) {
				// break;
				// }
				// }
				nowLong += read;
				if (nowLong == needLong) {
					fileOut.write(buf, 0, read);
					System.out.println("最后");
					break;
				}
				if (read == -1) {
					break;
				}
				fileOut.write(buf, 0, read);
			}
			fileOut.flush();
			fileOut.close();

			log.debug("--Receive ok [" + saveFile.getPath() + " ]");

		} catch (IOException e) {
			log.error(e, e);
			log.debug("---中断与服务器连接，无法接收消息");
			flag = false;
			if (fileOut != null) {
				try {
					fileOut.close();
				} catch (IOException e1) {
					log.error(e1, e1);
				}
			}
			return flag;
		}
		return flag;
	}

	/**
	 * 写入文件
	 * 
	 * @param out
	 * @param in
	 * @param file
	 * @throws IOException
	 */
	public void writeFile(ObjectOutputStream out, ObjectInputStream in, File file) throws IOException {
		if (file == null || !file.exists()) {
			throw new FileNotFoundException();
		}
		FileInputStream fis = null;
		try {
			// 写入 文件名 , 文件长度, 再 读取 跳过长度
			out.writeUTF(file.getName());
			out.flush();
			out.writeLong(file.length());
			out.flush();
			long skip = in.readLong();
			fis = new FileInputStream(file);
			fis.skip(skip);
			byte[] buf = new byte[BaseSocket.BUFFER_SIZE];

			log.debug("--开始发送--");

			while (true) {
				int read = 0;
				if (fis != null) {
					read = fis.read(buf);
				}
				if (read == -1) {
					break;
				}
				out.write(buf, 0, read);
				out.flush();
			}
			// byte[] bytes = BaseSocket.TRANSMIT_END.getBytes();
			// out.write(bytes);
			// out.flush();

			log.debug("<--发送end-->" + Thread.currentThread().getName());
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		} finally {
			if (fis != null) {
				try {
					fis.close();
				} catch (IOException e) {
					log.error(e, e);
				}
			}
		}
	}

	/**
	 * 读取对象
	 * 
	 * @param in
	 * @return
	 * @throws ClassNotFoundException
	 * @throws IOException
	 */
	public Object readObject(ObjectInputStream in) throws ClassNotFoundException, IOException {
		Object o = null;
		try {
			o = in.readObject();
		} catch (ClassNotFoundException ee) {
			log.error(ee, ee);
			throw ee;
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
		return o;
	}

	/**
	 * 写入对象
	 * 
	 * @param out
	 * @param obj
	 * @throws IOException
	 */
	public void writeObject(ObjectOutputStream out, Object obj) throws IOException {
		try {
			out.writeObject(obj);
			out.flush();
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
	}

	/**
	 * 读取字符串
	 * 
	 * @param in
	 * @return
	 * @throws IOException
	 */
	public String readUTF(ObjectInputStream in) throws IOException {
		String temp = "";
		try {
			temp = in.readUTF();
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
		return temp;
	}

	/**
	 * 写入字符串
	 * 
	 * @param out
	 * @param str
	 * @throws IOException
	 */
	public void writeUTF(ObjectOutputStream out, String str) throws IOException {
		try {
			out.writeUTF(str);
			out.flush();
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
	}

	/**
	 * 读取long
	 * 
	 * @param in
	 * @return
	 * @throws IOException
	 */
	public long readLong(ObjectInputStream in) throws IOException {
		long temp = 0;
		try {
			temp = in.readLong();
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
		return temp;
	}

	/**
	 * 写入long
	 * 
	 * @param out
	 * @param lon
	 * @throws IOException
	 */
	public void writeLong(ObjectOutputStream out, long lon) throws IOException {
		try {
			out.writeLong(lon);
			out.flush();
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
	}

	/**
	 * 读取boolean
	 * 
	 * @param in
	 * @return
	 * @throws IOException
	 */
	public boolean readBoolean(ObjectInputStream in) throws IOException {
		boolean temp = false;
		try {
			temp = in.readBoolean();
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
		return temp;
	}

	/**
	 * 写入boolean
	 * 
	 * @param out
	 * @param lon
	 * @throws IOException
	 */
	public void writeBoolean(ObjectOutputStream out, boolean val) throws IOException {
		try {
			out.writeBoolean(val);
			out.flush();
		} catch (IOException e) {
			log.error(e, e);
			throw e;
		}
	}

	public Operation todo(Operation o, ObjectOutputStream out, ObjectInputStream in) {
		Operation oper = new Operation(o.getType(), null);
		int type = HandleType.RETURN_SUCCESS;
		if (o.getType() == HandleType.FILE_DOWNLOAD) { // file download ok
			File file = new File("E:/111/360.exe"); // log4j.jar
			try {
				type = HandleType.RETURN_ERROR;
				if (file.exists() && file.isFile()) {
					this.writeFile(out, in, file);
					type = HandleType.RETURN_SUCCESS;
					oper.setObj(file.getName());
				}
			} catch (IOException e) {
				log.error(e, e);
				type = HandleType.RETURN_ERROR;
			}
		} else if (o.getType() == HandleType.FILE_UPLOAD) { // file upload ok
			boolean b = this.readFile("E:/zzz", out, in, false);
			if (b) {
				type = HandleType.RETURN_SUCCESS;
			} else {
				type = HandleType.RETURN_ERROR;
			}
		}

		oper.setType(type);
		return oper;

	}

	/**
	 * 从0.0.0.0:1234 中获取ip
	 * 
	 * @param s
	 * @return
	 */
	public static String getClientIp(SocketAddress s) {
		String ips = s.toString();
		ips = ips.replaceFirst("/", "");
		ips = ips.substring(0, ips.indexOf(":"));
		return ips;
	}

	public static boolean validateIp(String ip) {
		if (BaseSocket.IP_LIMIT) {
			String[] allowips = BaseSocket.ALLOW_IPS;
			for (String s : allowips) {
				if (s.equals(ip) || s == ip) {
					return true;
				}
			}
			return false;
		} else {
			return true;
		}
	}

}
